// import jsMd5 from 'js-md5'
// import JSEncrypt from 'jsencrypt'

String.prototype.format = function() {
	var args = arguments
	return this.replace(/{(\d+)}/g, function(m, i) {
		return args[i] || ''
	})
}

String.prototype.toMoney = function() {
	return num && num.toString().replace(/\d+/, function(s) {
		return s.replace(/(\d)(?=(\d{3})+$)/g, '$1,')
	})
}

Date.prototype.format = function(format) {
	format = format || 'yyyy-MM-dd HH:mm:ss'
	let f = function(m) {
		return m < 10 ? `0${m}` : m
	}
	let str = format.replace('yyyy', this.getFullYear())
	str = str.replace('MM', f(this.getMonth() + 1))
	str = str.replace('dd', f(this.getDate()))
	str = str.replace('HH', f(this.getHours()))
	str = str.replace('mm', f(this.getMinutes()))
	str = str.replace('ss', f(this.getSeconds()))
	return str
}

// 复制文本 兼容 h5
const copyText = function (text) {
  // #ifdef H5
  this.$copyText(text).then(
    res => {
      uni.showToast({
        title: '复制成功'
      })
    }
  )
  // #endif
  // #ifndef H5
  uni.setClipboardData({
    data: text,
    success: () => {
      uni.showToast({
        title: '复制成功'
      })
    }
  })
  // #endif
}

const md5 = function(val) {
	// return jsMd5(val)
}

/**
 * 加密密码
 * @param {*} pwd 密码
 * @param {*} publickey 加密公钥
 */
const encryptPwd = function(publickey, pwd) {
	var encrypt = new JSEncrypt()
	encrypt.setPublicKey(publickey)
	pwd = encrypt.encrypt(pwd)
	return pwd
}

// 64 位随机字符串
const randomString = () => {
	const str = '!@#*&%())#'
	const date = new Date().getTime() + ''
	const _str = md5(str + date) + md5(date)
	return _str
}
// 随机字符串2
export const randomId = () => {
  let s4 = function() {
      return (65536 * (1 + Math.random()) | 0).toString(16).substring(1);
  }
  return (s4() + s4() + "-" + s4() + "-4" + s4().substr(0, 3) + "-" + s4() + "-" + s4() + s4() + s4()).toUpperCase();
}

// 保留小数位，非四舍五入
const toFixed = (n, fixed) => ~~(Math.pow(10, fixed) * n) / Math.pow(10, fixed)

//部分密文显示
const ciphertext = function(value, start, end) {
	value = value + ''
	var _s = value.substring(0, start || 3)
	var _e = value.substring(value.length - end || 3, value.length)
	return `${_s}****${_e}`
}

// 移除结尾0
const removeEndZero = function(str) {
	// str = Number(str)
	str = str.toString().split('.')
	if (str[1]) {
		str[1] = str[1].replace(/[0]+$/, '')
	}
	return str[1] && str[1].length ? str.join('.') : str.join('')
}

// 如果是 '' 默认为 0.00 显示
const defaultZero = function(value) {
	return value === '' ? '0.00' : value
}

/*倒计时
t 倒计时长，单位秒
opt 参数
callback Function 带当前倒计时时间参数回调
format  String 倒计时模板
finished Function 倒计时完毕回调执行函数
 */
const countDown = function(t, opt) {
	const format = opt.format || 'dd HH:mm:ss'
	var f = function(m) {
		return m < 10 ? '0' + m : m
	}

	function a() {
		t = Math.max(t - 1, 0)
		if (t <= 0) {
			clearInterval(interval)
			typeof opt.finished === 'function' && opt.finished()
		}
		let str = format
		str = str.replace('dd', f(Math.floor(t / (60 * 60 * 24))))
		str = str.replace('HH', f(Math.floor(t / (60 * 60))))
		str = str.replace('mm', f(Math.floor(t / 60)))
		str = str.replace('ss', f(Math.floor(t % 60)))
		if (typeof opt.callback === 'function') {
			opt.callback(str)
		}
	}
	a()
	let interval = setInterval(a, 1000)
	return interval
}

//固定显示长度不足补0
const fitLen = function(num, length) {
	num = '0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' + num
	return num.slice(num.length - length)
}

// 数字人性化显示
const humanNum = function(number, digit = 2) {
	try {
		let _n = parseFloat(number),
			rst, unit = '';
		if (_n / 1000000000000 > 1) {
			rst = _n / 1000000000000;
			unit = '万亿';
		} else if (_n / 100000000 > 1) {
			rst = _n / 100000000;
			unit = '亿';
		} else if (_n / 10000 > 1) {
			rst = _n / 10000;
			unit = '万';
		} else {
			rst = _n;
		}
		return toFixed(rst, digit) + unit;
	} catch (e) {
		return number;
	}
}

//时间格式人性化
const humanTime2 = function(msec) {
	var days = parseInt(msec / 1000 / 60 / 60 / 24, 10); //计算剩余的天数
	var hours = parseInt(msec / 1000 / 60 / 60 % 24, 10); //计算剩余的小时
	var minutes = parseInt(msec / 1000 / 60 % 60, 10); //计算剩余的分钟
	var second = parseInt(msec / 1000 % 60, 10); //计算剩余的分钟
	days = days?`${days}天`:'';
	hours = hours?`${hours}小时`:'';
	minutes = minutes?`${minutes}分`:'';
	second = second?`${second}秒`:'';
	return days + hours + minutes + second
}
//时间格式人性化
const humanTime = function(msec) {
	var days = parseInt(msec / 1000 / 60 / 60 / 24, 10); //计算剩余的天数
	var hours = parseInt(msec / 1000 / 60 / 60 % 24, 10); //计算剩余的小时
	var minutes = parseInt(msec / 1000 / 60 % 60, 10); //计算剩余的分钟
	var second = parseInt(msec / 1000 % 60, 10); //计算剩余的分钟
	days = fitLen(days, 2);
	hours = fitLen(hours, 2);
	minutes = fitLen(minutes, 2);
	second = fitLen(second, 2);
	return {
		days,
		hours,
		minutes,
		second
	}
}

// 时间差 milliseconds
const humanize = function (milliseconds) {
	const UNITS = {
		'年': 31557600000,
		'月': 2629800000,
		'天': 86400000,
		'小时': 3600000,
		'分钟': 60000,
		'秒': 1000
	};
	let hum = '';
	for (let key in UNITS) {
		if (milliseconds >= UNITS[key]) {
			hum = Math.floor(milliseconds / UNITS[key]) + key + '前';
			break;
		}
	}
	return hum || '刚刚';
}

// 函数防抖：
const debounce = function(fn, wait) {
	let timer = null;
	return function() {
		let context = this
		if (timer) {
			clearTimeout(timer);
			timer = null;
		}
		timer = setTimeout(function() {
			fn.apply(context, arguments)
		}, wait)
	}
}

// 函数节流
const throttle = function(fn, gapTime) {
	let _lastTime = null;
	return function() {
		let _nowTime = +new Date()
		if (_nowTime - _lastTime > gapTime || !_lastTime) {
			fn(arguments);
			_lastTime = _nowTime
		}
	}
}

//判断是否为空对象、空数组
const isEmpty = function(obj) {
	//检验null和undefined
	if (!obj && obj !== 0 && obj !== '') {
		return true;
	}
	//检验数组
	if (Array.prototype.isPrototypeOf(obj) && obj.length === 0) {
		return true;
	}
	//检验对象
	if (Object.prototype.isPrototypeOf(obj) && Object.keys(obj).length === 0) {
		return true;
	}
	return false;
}

/**
 * 如果target(也就是FirstOBJ[key])存在，
 * 且是对象的话再去调用deepObjectMerge，
 * 否则就是FirstOBJ[key]里面没这个对象，需要与SecondOBJ[key]合并
 */
const deepObjectMerge = function(FirstOBJ, SecondOBJ) { // 深度合并对象
	for (var key in SecondOBJ) {
		FirstOBJ[key] = FirstOBJ[key] && FirstOBJ[key].toString() === "[object Object]" ?
			deepObjectMerge(FirstOBJ[key], SecondOBJ[key]) : FirstOBJ[key] = SecondOBJ[key];
	}
	return FirstOBJ;
}

function isObject(obj) {
	return Object.prototype.toString.call(obj) === '[object Object]'
}
function isArray(arr) {
	return Array.isArray(arr)
}
const objectMerge = function(target, ...arg) {
	return arg.reduce((acc, cur) => {
		return Object.keys(cur).reduce((subAcc, key) => {
			const srcVal = cur[key]
			if (isObject(srcVal)) {
				subAcc[key] = objectMerge(subAcc[key] ? subAcc[key] : {}, srcVal)
			} else if (isArray(srcVal)) {
				// series: []，下层数组直接赋值
				subAcc[key] = srcVal.map((item, idx) => {
					if (isObject(item)) {
						const curAccVal = subAcc[key] ? subAcc[key] : []
						return objectMerge(curAccVal[idx] ? curAccVal[idx] : {}, item)
					} else {
						return item
					}
				})
			} else {
				subAcc[key] = srcVal
			}
			return subAcc
		}, acc)
	}, target)
}

//比较版本号 @v1 新版本号 @v2当前版本号
const hasHighVersion = function(v1,v2) {
	if (typeof v1 === "number") {
		v1 = "0" + v1;
		v1 = v1.substr(1,v1.length-1);
	}
	if (typeof v2 === "number") {
		v2 = "0" + v2;
		v2 = v2.substr(1,v2.length-1);
	}
	if(v1 === v2){
		return false;
	}
	var v1Arry = v1.split("."),
		v2Arry = v2.split(".");

	for (var i = 0; i < v1Arry.length; i++) {
		if (i > v2Arry.length) {
			return true;
		}else{
			if (parseInt(v1Arry[i]) > parseInt(v2Arry[i])) {
				return true;
			}else if (parseInt(v1Arry[i]) < parseInt(v2Arry[i])) {
				return false;
			}
		}
	}
	return false;
}

const openURL = function(url){
	// #ifdef APP-PLUS
	plus.runtime.openURL(url);
	return
	// #endif
	if(window && window['cordova'] && window['cordova']['InAppBrowser']){
	  cordova.InAppBrowser.open(url, '_system', 'location=no,toolbar=yes,toolbarposition=top,closebuttoncaption=关闭')
	} else {
	  window.open(url, '_blank')
	}
}

//Object 转query字符串序列化
const serialize = function(obj) {
	let str = []
	for (let p in obj){
		if (obj.hasOwnProperty(p)) {
			str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]))
		}
	}
	return '?' + str.join("&")
}

// 密码至少6位，包含字母和数字
const isPassword = (val) => {
  return /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,18}$/.test(val)
}

// 获取元素坐标位置
const getElementTop = (element) => {
  let actualTop = element.offsetTop
  let current = element.offsetParent
  while (current !== null){
    actualTop += current.offsetTop
    current = current.offsetParent
  }
  return actualTop
}
const getElementLeft = (element) => {
  let actualLeft = element.offsetLeft
  let current = element.offsetParent
  while (current !== null){
    actualLeft += current.offsetLeft
    current = current.offsetParent
  }
  return actualLeft
}
const getElementXY = (element) => {
  let x = getElementLeft(element)
  let y = getElementTop(element)
  return {x, y}
}
const getNode = function(cls, success, it){
	uni.createSelectorQuery().in(it).select(cls).boundingClientRect(res=>{
		// console.log(res)
		success(res)
	}).exec()
}
const pretty = function (metaData) {
    function t(t) {
        this._key = [];
        this._tbl = {};
        for (var i = 0; i < 64; ++i) this._key[i] = e.charAt(t[i]),
            this._tbl[this._key[i]] = i;
        this._pad = e.charAt(64)
    }
    let e = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz$_~";
    t.prototype.dec = function(e) {
            var i, n, o, r, s = [],
                a = 0,
                l = 0;
            for (e = e.replace(/[^0-9A-Za-z$_~]/g, ""); a < e.length;) i = this._tbl[e.charAt(a++)],
                n = this._tbl[e.charAt(a++)],
                o = this._tbl[e.charAt(a++)],
                r = this._tbl[e.charAt(a++)],
                s[l++] = i << 2 | n >> 4,
                s[l++] = (15 & n) << 4 | o >> 2,
                s[l++] = (3 & o) << 6 | r;
            var h = e.slice(-2);
            return h.charAt(0) === this._pad ? s.length = s.length - 2 : h.charAt(1) === this._pad && (s.length = s.length - 1),
                t._1to2(s)
        },
        t._1to2 = function(t) {
            for (var e = "",
                    i = 0; i < t.length; ++i) {
                var n = t[i];
                e += String.fromCharCode(256 * n + t[++i])
            }
            return e
        };
	let i = [37, 20, 41, 59, 53, 8, 24, 5, 62, 31, 4, 32, 6, 50, 36, 63, 47, 42, 30, 39, 12, 3, 9, 45, 29, 23, 56, 2, 16, 61, 52, 44, 25, 35, 51, 0, 13, 43, 46, 40, 15, 27, 17, 57, 28, 54, 1, 60, 21, 22, 14, 49, 34, 33, 10, 58, 55, 19, 26, 11, 18, 48, 38, 7];
    let n = new t(i);
	console.log(n)
    return n.dec(metaData);
    // return JSON.parse(n.dec(metaData));
}

/**
 * 小数加法
 * @param {Number} arg1 
 * @param {Number} arg2 
 * @returns 
 */
const accAdd = (arg1, arg2) => {
    if (isNaN(arg1)) {
        arg1 = 0;
    }
    if (isNaN(arg2)) {
        arg2 = 0;
    }
    arg1 = Number(arg1);
    arg2 = Number(arg2);
    var r1, r2, m, c;
    try {
        r1 = arg1.toString().split(".")[1].length;
    }
    catch (e) {
        r1 = 0;
    }
    try {
        r2 = arg2.toString().split(".")[1].length;
    }
    catch (e) {
        r2 = 0;
    }
    c = Math.abs(r1 - r2);
    m = Math.pow(10, Math.max(r1, r2));
    if (c > 0) {
        var cm = Math.pow(10, c);
        if (r1 > r2) {
            arg1 = Number(arg1.toString().replace(".", ""));
            arg2 = Number(arg2.toString().replace(".", "")) * cm;
        } else {
            arg1 = Number(arg1.toString().replace(".", "")) * cm;
            arg2 = Number(arg2.toString().replace(".", ""));
        }
    } else {
        arg1 = Number(arg1.toString().replace(".", ""));
        arg2 = Number(arg2.toString().replace(".", ""));
    }
    return (arg1 + arg2) / m;
}


export {
	getNode,
	copyText,
	md5,
	encryptPwd,
	randomString,
	toFixed,
	defaultZero,
	ciphertext,
	removeEndZero,
	countDown,
	fitLen,
	humanNum,
	humanTime,
	humanTime2,
	humanize,
	debounce,
	throttle,
	isEmpty,
	deepObjectMerge,
	objectMerge,
	serialize,
	isPassword,
	hasHighVersion,
	openURL,
	getElementXY,
	getElementTop,
	getElementLeft,
	pretty,
	accAdd
}
